Amazon Redshift Serverlessでクロスアカウントのデータ共有を試してみました
データアナリティクス事業本部の鈴木です。
最近はAmazon Redshiftのデータ共有に凝っています。前回はRedshift Serverlessで同一アカウント内のデータ共有設定を確認してみましたが、今回はクロスアカウントでのデータ共有設定について確認してみました。
確認したかったこと
異なるアカウントに一つずつRedshift Serverlessインスタンスを起動し、データ共有の設定方法を確認しました。
特に以下を確認しました。
- アカウント間のデータ共有設定を実行してみて、コンシューマーアカウントのRedshift Serverlessインスタンスからプロデューサーアカウントのインスタンスのデータをクエリできることを確認する。
- コンシューマーアカウントのRedshift Serverlessインスタンスに一般ユーザーを作成し、データ共有から作ったデータベースがクエリできるか確認する。
- プロデューサーアカウントでデータ共有を無効化した時にどうなるのか確認する。
Redshift Serverlessインスタンスの準備
以下のブログで紹介されているCloudFormationテンプレートを少し修正してデプロイし、リソースを準備しました。
修正内容は以下になります。
AWS::RedshiftServerless::Namespace
でKmsKeyId
は指定せず、Redshift Serverlessの暗号化鍵にAWS_OWNED_KMS_KEY
を使いました。- 最小ベースキャパシティは8RPUとしました。
テンプレートを、プロデューサーアカウントとコンシューマーアカウントのそれぞれのCloudFormationからデプロイしました。
テンプレートは以下としましたが、長いのでトグルメニューにして隠しておきます。
CloudFormationテンプレート
AWSTemplateFormatVersion: "2010-09-09" Description: "Redshift Serverless and VPC" Parameters: Env: Type: "String" Default: "test" ProjectName: Type: "String" CidrBlock: Description: Please type the CidrBlock. Type: String Default: 192.168.0.0/22 BaseCapacity: Type: Number Default: 8 EnhancedVpcRouting: Type: String AllowedValues: - true - false Default: false PubliclyAccessible: Type: String AllowedValues: - true - false Default: true AdminUsername: Type: String Default: awsuser AdminUserPassword: Type: String Description: Must be 8-64 characters long. Must contain at least one uppercase letter, one lowercase letter and one number. Can be any printable ASCII character except “/”, ““”, or “@”. NoEcho: true MinLength: 8 MaxLength: 64 Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Sub ${CidrBlock} EnableDnsSupport: True EnableDnsHostnames: True InstanceTenancy: default Tags: - Key: Name Value: !Sub ${ProjectName}-redshiftserverless-${Env}-VPC InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Application Value: Ref: AWS::StackId - Key: Network Value: Public AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: Ref: VPC InternetGatewayId: Ref: InternetGateway PublicRouteTable: Type: AWS::EC2::RouteTable DependsOn: AttachGateway Properties: VpcId: Ref: VPC Tags: - Key: Name Value: !Sub | ${ProjectName}-redshiftserverless-${Env}-public-rtb - Key: Application Value: Ref: AWS::StackId PublicRoute: Type: AWS::EC2::Route DependsOn: AttachGateway Properties: RouteTableId: Ref: PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: Ref: InternetGateway Subnet1: Type: AWS::EC2::Subnet Properties: VpcId: Ref: VPC AvailabilityZone: !Select [ 0, !GetAZs ] CidrBlock: !Select [ 0, !Cidr [ !GetAtt VPC.CidrBlock, 4, 8 ]] Subnet2: Type: AWS::EC2::Subnet Properties: VpcId: Ref: VPC AvailabilityZone: !Select [ 1, !GetAZs ] CidrBlock: !Select [ 1, !Cidr [ !GetAtt VPC.CidrBlock, 4, 8 ]] Subnet3: Type: AWS::EC2::Subnet Properties: VpcId: Ref: VPC AvailabilityZone: !Select [ 2, !GetAZs ] CidrBlock: !Select [ 2, !Cidr [ !GetAtt VPC.CidrBlock, 4, 8 ]] Subnet1RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: Subnet1 RouteTableId: Ref: PublicRouteTable Subnet2RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: Subnet2 RouteTableId: Ref: PublicRouteTable Subnet3RouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: Ref: Subnet3 RouteTableId: Ref: PublicRouteTable RedshiftServerlessSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: Ref: VPC GroupDescription: Marker security group for Application server. Tags: - Key: Name Value: !Sub | ${ProjectName}-redshiftserverless-${Env}-sg RedshiftServerlessRole: Type: "AWS::IAM::Role" Properties: Path: "/" RoleName: !Sub "${ProjectName}-${Env}-redshift-role" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - redshift.amazonaws.com Action: sts:AssumeRole MaxSessionDuration: 3600 ManagedPolicyArns: - "arn:aws:iam::aws:policy/AmazonAthenaFullAccess" - "arn:aws:iam::aws:policy/AmazonS3FullAccess" - "arn:aws:iam::aws:policy/AWSGlueConsoleFullAccess" - "arn:aws:iam::aws:policy/AmazonRedshiftAllCommandsFullAccess" Description: "Allows Redshift clusters to call AWS services on your behalf." Tags: - Key: "Name" Value: !Sub "${ProjectName}-redshiftserverless-${Env}-redshift-role" RedshiftServerlessWorkGroup: Type: AWS::RedshiftServerless::Workgroup Properties: WorkgroupName: !Sub "${ProjectName}-${Env}-redshift-wg" BaseCapacity: !Ref BaseCapacity EnhancedVpcRouting: !Ref EnhancedVpcRouting NamespaceName: !Ref RedshiftServerlessNamespace PubliclyAccessible: !Ref PubliclyAccessible SecurityGroupIds: - !Ref RedshiftServerlessSecurityGroup SubnetIds: - !Ref Subnet1 - !Ref Subnet2 - !Ref Subnet3 RedshiftServerlessNamespace: Type: AWS::RedshiftServerless::Namespace Properties: NamespaceName: !Sub "${ProjectName}-${Env}-redshift-ns" AdminUsername: !Ref AdminUsername AdminUserPassword: !Ref AdminUserPassword DbName: !Sub "${ProjectName}-db" IamRoles: - !GetAtt RedshiftServerlessRole.Arn
データ共有の設定
ドキュメントとしては、以下の『Amazon Redshift データベース開発者ガイド』のAWSアカウント間でのデータ共有のページを参考にしました。Redshiftのデータ共有をそのまま使って設定する方法になります。
記載の手順に従って、クロスアカウントでのデータ共有ができることを確認しました。ただし、実際やってみると、ドキュメントを読んだだけよりも、必要な操作が多い印象だった(とはいえあくまで確認手順が増えたくらいの話です)ので、後の検証内容の紹介部分で補足します。
やってみる
今回は二つのアカウントを使います。マネジメントコンソールがライトモードである方がプロデューサーアカウント、ダークモードである方がプロデューサーアカウントです。Redshift query editor v2のコンソールは両方ダークモードで作業してしまったので、どちらなのかは随時記載します。
1. CloudFormationテンプレートのデプロイ
先に紹介したCloudFormationテンプレートを、プロデューサーアカウントとコンシューマーアカウントのそれぞれでデプロイしました。
2. プロデューサー側の設定(データ共有作成)
データの準備
まず、プロデューサーのRedshift Serverlessインスタンスに、Redshift query editor v2で、awsuser
スーパーユーザーで接続し、tickit
サンプルデータベースを作成しました。
データ共有の作成
以下のSQLを実行し、tickit_datashare
データ共有を作成しました。
CREATE DATASHARE tickit_datashare; ALTER DATASHARE tickit_datashare SET publicaccessible = TRUE;
次に、以下のSQLを実行して、tickit.users
サンプルテーブルをデータ共有に追加しました。
-- Add schema to datashare ALTER DATASHARE tickit_datashare ADD SCHEMA PUBLIC; -- Add table under schema to datashare ALTER DATASHARE tickit_datashare ADD SCHEMA tickit; ALTER DATASHARE tickit_datashare ADD TABLE tickit.users;
最後に、以下のSQLを実行して、コンシューマーアカウントにデータ共有を行うよう設定しました。
-- <コンシューマーアカウントのアカウントID>は適したものに変えてください GRANT USAGE ON DATASHARE tickit_datashare TO ACCOUNT '<コンシューマーアカウントのアカウントID>';
ここまでで、アカウントで作成されたデータ共有
画面に、作業で作成したデータ共有ができていることを確認できました。
データ共有ステータス
が必要なアクション
になっていました。これは次で説明します。
3. プロデューサー側の設定(データコンシューマーの承認)
アカウント内のデータ共有では不要でしたが、クロスアカウントではデータコンシューマーの承認をする必要がありました。
個別のデータ共有を開きました。コンシューマーのステータス
がPending authorization
になっています。
データコンシューマーを選び、データコンシューマーID
が合っていることを確認して、承認
を押しました。
これでコンシューマーのステータス
が承認済み
になりました。
4. コンシューマー側の設定(データ共有の関連付け)
次に、コンシューマーアカウントの設定をしていきました。
データ共有で他のアカウントから
タブを開くと、tickit_datashare
があることを確認できました。ここでもデータ共有ステータス
が 必要なアクション
になっているので作業をしました。
tickit_datashare
を選択し、Associtate
を押しました。
データ共有を関連づける対象を選択しました。今回は、コンシューマーアカウントにある、今回作成したRedshift Serverlessインスタンスだけを指定しました。
データ共有ステータス
がアクティブ
になりました。
5. コンシューマー側の設定(データ共有からのデータベース作成)
まず、コンシューマー側のRedshift Serverlessインスタンスからデータ共有が確認できるか、Redshift query editor v2で確認しました。
コンシューマー側のRedshift Serverlessインスタンスの適当なデータベースにawsuser
で接続し、以下のSQLを実行しました。
SHOW DATASHARES LIKE 'tickit_%';
関連付けをしているため、データ共有が見えました。
次に、以下のSQLを実行して、データ共有からデータベースを作成しました。
-- <コンシューマーアカウントのアカウントID>は適したものに変えてください -- <プロデューサーRedshift ServerlessのNAMESPACE>は適したものに変えてください CREATE DATABASE consumer_tickit FROM DATASHARE tickit_datashare OF ACCOUNT '<プロデューサーアカウントのアカウントID>' NAMESPACE '<プロデューサーRedshift ServerlessのNAMESPACE>';
検索すると、確かにデータを取得できました。
そのほかに確認したこと
プロデューサーに追加したデータが反映されることの確認
改めてではありますが、プロデューサーのRedshift Serverless側で追加したデータが、コンシューマー側で取得できるのかについて確認しました。
プロデューサーアカウントで、Redshift query editor v2にてインスタンスに接続し、以下のSQLを実行してusers
テーブルにデータを追加しました。
insert into tickit.users values ('000','Samaple','Samaple','Samaple','Samaple','OK','Sample.nulla@magnisdis.ca','(295) Samaple',null,false,false,false,null,true,null,null,null,null)
コンシューマーアカウントで、Redshift query editor v2にてインスタンスに接続し、consumer_tickit.tickit.users
テーブルにデータが反映されているか確認できました。
コンシューマーアカウントの一般ユーザーで共有されたデータを確認する
コンシューマーアカウントにて、Redshift query editor v2でawsuser
スーパーユーザーを使って適当なユーザーを作成しました。このユーザーから共有されたconsumer_tickit.tickit.users
テーブルを確認できるか試しました。
コンシューマーアカウントにて、以下のSQLを実行しました。
CREATE USER testuser1 WITH PASSWORD 'testPASS111';
Redshift query editor v2で、testuser1
で接続しました。
この時点では、consumer_tickit
データベースが見られませんでした。
再びawsuser
での接続に切り替え、consumer_tickit
データベースへの権限を付与しました。
GRANT USAGE ON DATABASE consumer_tickit TO testuser1;
再度testuser1
で接続すると、利用できるようになりました。
プロデューサー側からデータ共有を無効化した場合の挙動
最後に、プロデューサー側からデータ共有を無効化した場合の挙動を確認しました。これはドキュメントにオプションとして記載されていたもので、データ共有が不要になった場合の操作になります。
まず、プロデューサー側からawsuser
で以下のSQLを実行し、tickit_datashare
データ共有を無効化しました。
-- <コンシューマーアカウントのアカウントID>は適したものに変えてください REVOKE USAGE ON DATASHARE tickit_datashare FROM ACCOUNT '<コンシューマーアカウントのアカウントID>';
これでRedshiftのコンソールからはデータ共有が削除されました。
コンシューマー側でもRedshiftのコンソールからはデータ共有が削除されました。
ただし、コンシューマー側のインスタンスに接続すると、データベースは残っていたので、これは手動で削除する必要がありそうでした。
例えば以下のようにSQLを実行して削除できました。
DROP DATABASE consumer_tickit;
最後に
今回はAmazon Redshift Serverlessで、クロスアカウントでのデータ共有設定について確認してみました。同一アカウントのときよりも少し操作が増えていましたが、事故防止の一手間という程度で、とても簡単に設定できました。
アカウントを跨いでも、Redshift間であればETLなしでデータを連携できるのは非常に強力です。Redshiftをデータウェアハウスの選択肢に入れておられる方は、ぜひご確認頂ければと思います。